package com.element.oauth2.resource.config;

import com.element.oauth2.annotation.AuthExcludeRequest;
import com.element.oauth2.annotation.EnableGlobalResourceServer;
import com.element.oauth2.utils.PathMatcherUtil;
import lombok.Getter;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.condition.PathPatternsRequestCondition;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;


import javax.annotation.Resource;
import java.util.*;

/**
 * @auther zhangwj
 * @date 2021/4/14 下午8:06
 */
@Configuration
public class PermitAllUrlProperties implements InitializingBean {

    @Resource
    private WebApplicationContext applicationContext;

    @Getter
    private final List<String> ignoreUrls = new ArrayList<>();

    @Override
    public void afterPropertiesSet() {
        // 添加默认错误返回地址
        ignoreUrls.add("/error");
        RequestMappingHandlerMapping mapping = applicationContext.getBean("requestMappingHandlerMapping", RequestMappingHandlerMapping.class);
        Map<RequestMappingInfo, HandlerMethod> map = mapping.getHandlerMethods();
        map.keySet().forEach(info -> {
            HandlerMethod handlerMethod = map.get(info);
            // TODO 获取方法上边的注解 后期可加入字段判断
            AuthExcludeRequest method = AnnotationUtils.findAnnotation(handlerMethod.getMethod(), AuthExcludeRequest.class);
            Optional.ofNullable(method)
                    .ifPresent(inner -> {
                        PathPatternsRequestCondition requestCondition = info.getPathPatternsCondition();
                        if (null != requestCondition) {
                            ignoreUrls.addAll(requestCondition.getPatternValues());
                        }
                    });
            // TODO 获取类上边的注解 后期可加入字段判断
            AuthExcludeRequest controller = AnnotationUtils.findAnnotation(handlerMethod.getBeanType(), AuthExcludeRequest.class);
            Optional.ofNullable(controller)
                    .ifPresent(inner -> {
                        PathPatternsRequestCondition requestCondition = info.getPathPatternsCondition();
                        if (null != requestCondition) {
                            ignoreUrls.addAll(requestCondition.getPatternValues());
                        }
                    });
        });
        Map<String, Object> beans = applicationContext.getBeansWithAnnotation(EnableGlobalResourceServer.class);
        if (!CollectionUtils.isEmpty(beans)) {
            beans.forEach((key, value) -> {
                Class<?> clazz = value.getClass();
                EnableGlobalResourceServer security = AnnotationUtils.findAnnotation(clazz, EnableGlobalResourceServer.class);
                if (null != security) {
                    String[] excludes = security.exclude();
                    if (null != excludes && excludes.length > 0) {
                        ignoreUrls.addAll(Arrays.asList(excludes));
                    }
                }
            });
        }
    }

    public boolean hasMatcher(String path) {
        if (!CollectionUtils.isEmpty(this.getIgnoreUrls())) {
            return PathMatcherUtil.hasMatcher(this.getIgnoreUrls(), path);
        }
        return false;
    }
}
